package com.ai.trickycards.widgets

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.LightingColorFilter
import android.graphics.Paint
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.graphics.RectF
import android.util.AttributeSet
import android.view.View
import androidx.core.content.ContextCompat
import androidx.core.content.res.use
import com.ai.trickycards.R
import com.ai.trickycards.entity.enumeration.PokerRankEnum
import com.ai.trickycards.entity.enumeration.PokerSuitEnum
import kotlin.math.roundToInt

/**
 * 扑克牌View
 */
class PokerCardView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    private val density by lazy {
        context.resources.displayMetrics.density
    }

    fun setCard(rank: PokerRankEnum, suit: PokerSuitEnum) {
        this.rank = rank
        this.suit = suit
        invalidate() // 重新绘制视图
    }

    /**
     * 扑克牌显示类型
     */
    enum class ShowType(val bgRes: Int) {
        Content01(0),
        Content02(0),
        Content03(0),
        Content04(0),
        Content05(0),
        Back01(R.mipmap.poker_back01),
        Back02(R.mipmap.poker_back02),
        Back03(R.mipmap.poker_back03),
        Back04(R.mipmap.poker_back04),
        Back05(R.mipmap.poker_back05),
        Back06(R.mipmap.poker_back06),
        Back07(R.mipmap.poker_back07),
        Back08(R.mipmap.poker_back08)
    }

    /**
     * 显示样式类型
     */
    var showType = ShowType.Content01
        set(value) {
            field = value
            invalidate()
        }

    /**
     * 扑克牌花色
     */
    var suit = PokerSuitEnum.Spade
        set(value) {
            field = value
            invalidate()
        }

    /**
     * 扑克牌点数
     */
    var rank = PokerRankEnum.RankA
        set(value) {
            field = value
            invalidate()
        }

    /**
     * 是否显示罩遮
     */
    var mask = false
        set(value) {
            field = value
            invalidate()
        }

    /**
     * 遮罩颜色
     */
    var maskColor = Color.parseColor("#52000000")
        set(value) {
            field = value
            invalidate()
        }

    /**
     * 是否显示阴影
     */
    var shadow = false
        set(value) {
            field = value
            invalidate()
        }

    private val paint = Paint()
    private val radioScale = 0.0625f // 卡牌圆角与卡牌宽度的占比
    private val borderWidthScale = 0.0625f // 边框与卡牌宽度的占比
    private val suitOffsetYScale = 0.05f // 点数距离顶部偏移距离与卡牌宽度的占比
    private val shadowScale = 0.0625f // 阴影缩放比

    init {
        context.obtainStyledAttributes(attrs, R.styleable.PokerCardView).use {
            val typeIndex = it.getInt(R.styleable.PokerCardView_pcvShowType, 0)
            showType = ShowType.entries.toTypedArray()[typeIndex]

            val suitIndex = it.getInt(R.styleable.PokerCardView_pcvSuit, 0)
            suit = PokerSuitEnum.entries.toTypedArray()[suitIndex]

            val rankNum = it.getInt(R.styleable.PokerCardView_pcvRank, PokerRankEnum.RankA.num)
            rank = PokerRankEnum.valueOfNum(rankNum)

            mask = it.getBoolean(R.styleable.PokerCardView_pcvMask, mask)
            maskColor = it.getColor(R.styleable.PokerCardView_pcvMaskColor, maskColor)

            shadow = it.getBoolean(R.styleable.PokerCardView_pcvShadow, shadow)
        }
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        if (showType in listOf(
                ShowType.Content01,
                ShowType.Content02,
                ShowType.Content03,
                ShowType.Content04,
                ShowType.Content05
            ) && (suit == PokerSuitEnum.Joker || rank == PokerRankEnum.Joker)
        ) {
            drawJoker(canvas)
            return
        }
        when (showType) {
            ShowType.Content01 -> drawContent01(canvas)
            ShowType.Content02 -> drawContent02(canvas)
            ShowType.Content03 -> drawContent03(canvas)
            ShowType.Content04 -> drawContent04(canvas)
            ShowType.Content05 -> drawContent05(canvas)
            else -> drawBack(canvas)
        }
    }

    /**
     * 绘制内容背景
     */
    private fun drawContentBg(canvas: Canvas, bgColor: Int) {
        paint.reset()
        paint.isAntiAlias = true
        paint.color = bgColor
        paint.style = Paint.Style.FILL_AND_STROKE
        paint.strokeWidth = width * borderWidthScale
        val strokeHalf = paint.strokeWidth / 2
        val rect = RectF(strokeHalf, strokeHalf, width - strokeHalf, height - strokeHalf)
        //val rect = RectF(0f, 0f, width.toFloat(), height.toFloat())
        val radio = width * radioScale
        if (shadow) {
            paint.setShadowLayer(width * shadowScale * 2, -width * shadowScale, 0f, Color.parseColor("#40000000"))
        }
        canvas.drawRoundRect(rect, radio, radio, paint)
    }

    /**
     * 绘制点数+花色
     */
    private fun drawContent01(canvas: Canvas) {
        val fontScale = 0.5625f // 字号与卡牌宽度的占比
        val bigSuitSizeScale = 0.75f // 大花色图标的大小与卡牌宽度的占比
        val bigSuitBottomMargin = 0.0625f // 大花色图标距离底部的距离与卡牌高度的占比

        drawContentBg(canvas, Color.WHITE)

        paint.reset()
        paint.isAntiAlias = true
        // 绘制点数
        paint.color = ContextCompat.getColor(context, suit.color)
        paint.textSize = width * fontScale
        paint.typeface = resources.getFont(R.font.roboto_bold_700)
        paint.textAlign = Paint.Align.CENTER
        val fontMetrics = paint.fontMetrics
        val textCenterX = width / 2f
        val textOffsetY = width * suitOffsetYScale
        canvas.drawText(rank.text, textCenterX, -fontMetrics.ascent + textOffsetY, paint)

        // 绘制下面的大图标花色
        val suit = ContextCompat.getDrawable(context, suit.icon)!!
        val bigSuitSize = (width * bigSuitSizeScale).roundToInt()
        val bigSuitMargin = (height * bigSuitBottomMargin).roundToInt()
        val bigSuitLeft = (width - bigSuitSize) / 2
        val bigSuitTop = height - bigSuitMargin - bigSuitSize
        suit.setBounds(bigSuitLeft, bigSuitTop, bigSuitLeft + bigSuitSize, bigSuitTop + bigSuitSize)
        suit.draw(canvas)

        if (mask) {
            drawMask(canvas)
        }
    }

    /**
     * 绘制点数+花色
     */
    private fun drawContent02(canvas: Canvas) {
        val fontScale = 0.5f // 字号与卡牌宽度的占比
        val fontCenterXScale = 0.3125f // 点数中心X与卡牌宽度的占比
        val smallSuitSizeScale = 0.1875f // 小花色图标的大小与卡牌宽度的占比
        val smallSuitTopScale = 0.6f // 小花色图标上边边距与卡牌宽度的占比
        val bigSuitSizeScale = 0.625f // 大花色图标的大小与卡牌宽度的占比
        val bigSuitBottomMargin = 0.0625f // 大花色图标距离底部的距离与卡牌高度的占比

        // 绘制背景
        drawContentBg(canvas, Color.WHITE)

        paint.reset()
        paint.isAntiAlias = true
        // 绘制点数
        paint.color = ContextCompat.getColor(context, suit.color)
        paint.textSize = width * fontScale
        paint.typeface = resources.getFont(R.font.roboto_bold_700)
        paint.textAlign = Paint.Align.CENTER
        val fontMetrics = paint.fontMetrics
        val textCenterX = width * fontCenterXScale
        val textOffsetY = width * suitOffsetYScale
        canvas.drawText(rank.text, textCenterX, -fontMetrics.ascent + textOffsetY, paint)

        // 绘制点数下边的花色
        val suit = ContextCompat.getDrawable(context, suit.icon)!!
        val smallSuitSize = (width * smallSuitSizeScale).roundToInt()
        val smallSuitLeft = (textCenterX - smallSuitSize / 2).roundToInt()
        val smallSuitTop = (width * smallSuitTopScale).roundToInt()
        suit.setBounds(smallSuitLeft, smallSuitTop, smallSuitLeft + smallSuitSize, smallSuitTop + smallSuitSize)
        suit.draw(canvas)

        // 绘制下面的大图标花色
        val bigSuitSize = (width * bigSuitSizeScale).roundToInt()
        val bigSuitMargin = (height * bigSuitBottomMargin).roundToInt()
        val bigSuitLeft = width - bigSuitSize - bigSuitMargin
        val bigSuitTop = height - bigSuitMargin - bigSuitSize
        suit.setBounds(bigSuitLeft, bigSuitTop, bigSuitLeft + bigSuitSize, bigSuitTop + bigSuitSize)
        suit.draw(canvas)

        if (mask) {
            drawMask(canvas)
        }
    }


    /**
     * 绘制点数+花色
     */
    private fun drawContent03(canvas: Canvas) {
        val fontScale = 0.5f // 字号与卡牌宽度的占比
        val fontCenterXScale = 0.25f // 点数中心X与卡牌宽度的占比
        val smallSuitSizeScale = 0.1875f // 小花色图标的大小与卡牌宽度的占比
        val smallSuitTopScale = 0.6f // 小花色图标上边边距与卡牌宽度的占比

        // 绘制背景
        drawContentBg(canvas, Color.WHITE)

        paint.reset()
        paint.isAntiAlias = true
        // 绘制点数
        paint.color = ContextCompat.getColor(context, suit.color)
        paint.textSize = width * fontScale
        paint.typeface = resources.getFont(R.font.roboto_bold_700)
        paint.textAlign = Paint.Align.CENTER
        val fontMetrics = paint.fontMetrics
        val textCenterX = width * fontCenterXScale
        val textOffsetY = width * suitOffsetYScale
        canvas.drawText(rank.text, textCenterX, -fontMetrics.ascent + textOffsetY, paint)

        // 绘制点数下边的花色
        val suit = ContextCompat.getDrawable(context, suit.icon)!!
        val smallSuitSize = (width * smallSuitSizeScale).roundToInt()
        val smallSuitLeft = (textCenterX - smallSuitSize / 2).roundToInt()
        val smallSuitTop = (width * smallSuitTopScale).roundToInt()
        suit.setBounds(smallSuitLeft, smallSuitTop, smallSuitLeft + smallSuitSize, smallSuitTop + smallSuitSize)
        suit.draw(canvas)

        // 绘制下面的镜面
        canvas.save()
        canvas.rotate(180f, width / 2f, height / 2f)
        canvas.drawText(rank.text, textCenterX, -fontMetrics.ascent, paint)
        suit.draw(canvas)
        canvas.restore()

        if (mask) {
            drawMask(canvas)
        }
    }

    /**
     * 绘制点数+花色
     */
    private fun drawContent04(canvas: Canvas) {
        val fontScale = 0.5f // 字号与卡牌宽度的占比
        val fontCenterXScale = 0.3125f // 点数中心X与卡牌宽度的占比
        val bigSuitSizeScale = 0.625f // 大花色图标的大小与卡牌宽度的占比
        val bigSuitBottomMargin = 0.125f // 大花色图标距离底部的距离与卡牌高度的占比

        // 绘制背景
        drawContentBg(canvas, Color.WHITE)

        paint.reset()
        paint.isAntiAlias = true
        // 绘制点数
        paint.color = ContextCompat.getColor(context, suit.color)
        paint.textSize = width * fontScale
        paint.typeface = resources.getFont(R.font.roboto_bold_700)
        paint.textAlign = Paint.Align.CENTER
        val fontMetrics = paint.fontMetrics
        val textCenterX = width * fontCenterXScale
        val textOffsetY = width * suitOffsetYScale
        canvas.drawText(rank.text, textCenterX, -fontMetrics.ascent + textOffsetY, paint)

        // 绘制边框
        paint.style = Paint.Style.STROKE
        paint.strokeWidth = width * borderWidthScale
        val borderHalf = paint.strokeWidth / 2
        val radio = width * radioScale
        canvas.drawRoundRect(borderHalf, borderHalf, width - borderHalf, height - borderHalf, radio, radio, paint)


        // 绘制下面的大图标花色
        paint.style = Paint.Style.FILL
        val suit = ContextCompat.getDrawable(context, suit.icon)!!
        val bigSuitSize = (width * bigSuitSizeScale).roundToInt()
        val bigSuitMargin = (width * bigSuitBottomMargin).roundToInt()
        val bigSuitLeft = (width - bigSuitSize) / 2
        val bigSuitTop = height - bigSuitMargin - bigSuitSize
        suit.setBounds(bigSuitLeft, bigSuitTop, bigSuitLeft + bigSuitSize, bigSuitTop + bigSuitSize)
        suit.draw(canvas)

        if (mask) {
            drawMask(canvas)
        }
    }

    /**
     * 绘制点数+花色
     */
    private fun drawContent05(canvas: Canvas) {
        val fontScale = 0.5f // 字号与卡牌宽度的占比
        val fontCenterXScale = 0.3125f // 点数中心X与卡牌宽度的占比
        val bigSuitSizeScale = 0.625f // 大花色图标的大小与卡牌宽度的占比
        val bigSuitBottomMargin = 0.125f // 大花色图标距离底部的距离与卡牌高度的占比

        // 绘制背景
        drawContentBg(canvas, ContextCompat.getColor(context, suit.color))

        paint.reset()
        paint.isAntiAlias = true
        // 绘制点数
        paint.color = Color.WHITE
        paint.textSize = width * fontScale
        paint.typeface = resources.getFont(R.font.roboto_bold_700)
        paint.textAlign = Paint.Align.CENTER
        val fontMetrics = paint.fontMetrics
        val textCenterX = width * fontCenterXScale
        val textOffsetY = width * suitOffsetYScale
        canvas.drawText(rank.text, textCenterX, -fontMetrics.ascent + textOffsetY, paint)


        // 绘制下面的大图标花色
        paint.style = Paint.Style.FILL
        val suit = ContextCompat.getDrawable(context, suit.icon)!!
        val bigSuitSize = (width * bigSuitSizeScale).roundToInt()
        val bigSuitMargin = (width * bigSuitBottomMargin).roundToInt()
        val bigSuitLeft = (width - bigSuitSize) / 2
        val bigSuitTop = height - bigSuitMargin - bigSuitSize
        suit.setBounds(bigSuitLeft, bigSuitTop, bigSuitLeft + bigSuitSize, bigSuitTop + bigSuitSize)
        suit.colorFilter = LightingColorFilter(Color.WHITE, Color.WHITE)
        suit.draw(canvas)

        if (mask) {
            drawMask(canvas)
        }
    }

    /**
     * 绘制花牌
     */
    private fun drawJoker(canvas: Canvas) {
        val fontTopScale = 0.09375f // 字体距卡牌顶部的距离与宽度的比
        val fontScale = 0.25f // 字号与卡牌宽度的占比
        val bigSuitSizeScale = 0.75f // 大花色图标的大小与卡牌宽度的占比
        val bigSuitBottomMargin = 0.125f // 大花色图标距离底部的距离与卡牌高度的占比

        // 绘制背景
        drawContentBg(canvas, Color.WHITE)

        paint.reset()
        paint.isAntiAlias = true
        // 绘制点数
        paint.color = ContextCompat.getColor(context, suit.color)
        paint.textSize = width * fontScale
        paint.typeface = resources.getFont(R.font.roboto_black_900)
        paint.textAlign = Paint.Align.CENTER
        val fontMetrics = paint.fontMetrics
        val textCenterX = width / 2f
        val textOffsetY = width * suitOffsetYScale + width * fontTopScale
        canvas.drawText(rank.text, textCenterX, -fontMetrics.ascent + textOffsetY, paint)

        // 绘制图标
        paint.style = Paint.Style.FILL
        val suit = ContextCompat.getDrawable(context, suit.icon)!!
        val bigSuitSize = (width * bigSuitSizeScale).roundToInt()
        val bigSuitMargin = (width * bigSuitBottomMargin).roundToInt()
        val bigSuitLeft = (width - bigSuitSize) / 2
        val bigSuitTop = height - bigSuitMargin - bigSuitSize
        suit.setBounds(bigSuitLeft, bigSuitTop, bigSuitLeft + bigSuitSize, bigSuitTop + bigSuitSize)
        suit.draw(canvas)

        if (mask) {
            drawMask(canvas)
        }
    }


    /**
     * 绘制背景
     */
    private fun drawBack(canvas: Canvas) {
        val drawable = ContextCompat.getDrawable(context, showType.bgRes)!!.mutate()
        drawable.setBounds(0, 0, width, height)
        if (mask) {
            drawable.colorFilter = PorterDuffColorFilter(maskColor, PorterDuff.Mode.SRC_ATOP)
        }

        drawable.draw(canvas)
    }

    /**
     * 绘制半透明遮罩
     */
    private fun drawMask(canvas: Canvas) {
        paint.reset()
        paint.isAntiAlias = true
        val rect = RectF(0f, 0f, width.toFloat(), height.toFloat())
        val radio = width * radioScale + 3
        paint.color = maskColor
        paint.style = Paint.Style.FILL
        canvas.drawRoundRect(rect, radio, radio, paint)
    }

}